package com.atguigu.aiproject.controller.ai;

import com.atguigu.aiproject.dto.AiCreateTextRequestDTO;
import com.atguigu.aiproject.entity.Creation;
import com.atguigu.aiproject.entity.Result;
import com.atguigu.aiproject.service.CreationService;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import org.springframework.ai.chat.client.ChatClient;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.web.bind.annotation.*;
import org.springframework.web.multipart.MultipartFile;
import reactor.core.publisher.Flux;

import java.io.File;
import java.io.IOException;
import java.net.URI;
import java.net.http.HttpClient;
import java.net.http.HttpRequest;
import java.net.http.HttpResponse;
import java.nio.file.Files;
import java.nio.file.Path;
import java.nio.file.Paths;
import java.util.Date;

@RestController
@CrossOrigin
@RequestMapping("/ai/text")
public class TextController {
    @Autowired
    @Qualifier("textClient")
    private ChatClient textClient;
    @Autowired
    private CreationService creationService;
    @Value("${system.file_save_path}")
    private String filePath;//系统默认保存文件路径

    @PostMapping(value = "/create",  produces = "text/event-stream;charset=utf-8")
    public Flux<String> aiCreate(@RequestBody AiCreateTextRequestDTO aiCreateTextRequestDTO) {
        String ask = aiCreateTextRequestDTO.getAsk();
        String type = aiCreateTextRequestDTO.getType();

        return textClient.prompt()
                .system(generatePromptByType(type))
                .user(ask)
                .stream()
                .content();
    }


    // 根据文本类型生成不同的提示词
    public String generatePromptByType(String type) {
        return switch (type) {
            case "story" -> """
                请根据以下主题创作一个有趣的故事：
                主题：%s
                要求：
                1. 故事要有清晰的开头、发展和结尾
                2. 角色鲜明，情节引人入胜
                3. 字数在500-1000字之间
                4. 语言生动形象，适合大众阅读
                """;

            case "poetry" -> """
                请根据以下主题创作一首诗歌：
                主题：%s
                要求：
                1. 诗歌要有韵律和节奏感
                2. 语言优美，富有意境
                3. 表达情感真挚，能引起共鸣
                4. 可以是现代诗或古体诗风格
                """;

            case "blessing" -> """
                请根据以下场合和对象创作一段祝福语：
                场合和对象：%s
                要求：
                1. 祝福语要真诚温馨，富有感染力
                2. 语言简洁明了，朗朗上口
                3. 符合特定场合的氛围
                4. 可以适当个性化定制
                """;

            case "event" -> """
                请根据以下需求制定一份活动安排：
                需求：%s
                要求：
                1. 活动安排要详细具体，包括时间、地点、流程等
                2. 考虑到参与人员的需求和实际情况
                3. 合理分配时间和资源
                4. 预留应急处理时间
                """;

            case "article" -> """
                请根据以下主题撰写一篇文章：
                主题：%s
                要求：
                1. 文章结构清晰，逻辑严谨
                2. 内容充实，有深度和广度
                3. 语言准确流畅，适合正式场合
                4. 字数在800-1500字之间
                """;

            default -> """
                请根据以下主题创作相关内容：
                主题：%s
                请创作符合该主题的文本内容。
                """;
        };
    }
    /**
     * 获取创作列表
     * @param pageNum
     * @param pageSize
     * @param search
     * @return
     */
    @GetMapping("/list")
    public Result<?> list(
            @RequestParam(value = "pageNum",defaultValue = "1") int pageNum,
            @RequestParam(value = "pageSize",defaultValue = "2")int pageSize,
            @RequestParam(value = "search",defaultValue = "")String search) {
        Page<Creation> page=new Page<>(pageNum,pageSize);
        QueryWrapper<Creation> qw = new QueryWrapper<>();
        qw.lambda().like(!search.isEmpty(),Creation::getTitle,search)//模糊查询
                .or()
                .like(!search.isEmpty(),Creation::getContent,search)
                .orderByDesc(Creation::getCreateTime).orderByDesc(Creation::getClick);//排序
        creationService.page(page, qw);
        return Result.success(page);
    }
    /**
     * 发布创作
     * @param creation
     * @param pic  客户上传的配图
     * @param ai_img_url  ai生成的图片的url
     * @return
     */
    @PostMapping("/publish")
    public Result<?> publish(
            @RequestBody Creation creation,
            @RequestParam String ai_img_url,
            MultipartFile pic) throws IOException {
        if(!ai_img_url.isEmpty()){
            String fileName = saveImageFromUrl(ai_img_url, filePath);//保存ai生成的图片
            creation.setImg(fileName);
        }
        if(!pic.isEmpty()){//图片不为空
            //将上传的图片文件保存到指定目录下, 文件名用当前时间戳+文件名
            String fileName = new Date().getTime() + pic.getOriginalFilename();
            pic.transferTo(new File(filePath+ fileName));
            //将文件名保存到数据库
            creation.setImg(fileName);
        }
        creation.setClick(0);//设置点击数为零
        creationService.save(creation);//保存到数据库
        return Result.success();
    }
    /**
     * 从指定URL下载图片并保存到本地文件夹
     * @param imageUrl 要下载的图片URL地址
     * @param dir 图片保存的本地目录路径
     * @return 保存后的文件名，如果下载失败则返回null
     * @throws IOException 当发生IO异常时抛出
     */
    public String saveImageFromUrl(String imageUrl, String dir) throws IOException {
        // 创建Java原生HttpClient实例，用于发送HTTP请求
        HttpClient httpClient = HttpClient.newHttpClient();

        // 构建HTTP GET请求，指定要下载图片的URL
        HttpRequest request = HttpRequest.newBuilder()
                .uri(URI.create(imageUrl))  // 将字符串URL转换为URI对象
                .build();                   // 构建请求对象

        try {
            // 发送HTTP请求并指定响应体处理器为字节数组处理器
            HttpResponse<byte[]> response = httpClient.send(request, HttpResponse.BodyHandlers.ofByteArray());

            // 检查HTTP响应状态码是否为成功状态(200-299)
            if (response.statusCode() >= 200 && response.statusCode() < 300) {
                // 获取响应体中的图片字节数据
                byte[] imageBytes = response.body();

                // 从URL中提取文件名（去掉查询参数部分，获取最后一个/后的文件名）
                String fileName = imageUrl.split("\\?")[0].substring(imageUrl.lastIndexOf("/") + 1);

                // 构建图片保存的完整路径
                Path imagePath = Paths.get(dir, fileName);

                // 将图片字节数据写入到指定文件路径
                Files.write(imagePath, imageBytes);

                // 返回保存的文件名
                return fileName;
            }
            // 如果响应状态码不是成功状态，返回null表示下载失败
            return null;
        } catch (InterruptedException e) {
            // 如果请求被中断，将中断异常转换为IO异常抛出
            throw new IOException("下载图片被中断", e);
        }
    }
}
